#region Usings

using System.Windows;
using Box2DX.Common;
using Math=System.Math;

#endregion

namespace SilverBox.Physics
{
    public struct Vector
    {
        internal double _x;
        internal double _y;

        public Vector(double x, double y)
        {
            _x = x;
            _y = y;
        }

        public double X
        {
            get { return _x; }
            set { _x = value; }
        }

        public double Y
        {
            get { return _y; }
            set { _y = value; }
        }

        public double LengthSquared
        {
            get { return ((X*X) + (Y*Y)); }
        }

        public double Length
        {
            get { return Math.Sqrt((_x*_x) + (_y*_y)); }
        }

        public static bool operator ==(Vector v1, Vector v2)
        {
            if ((v1.X == v2.X) && (v1.Y == v2.Y))
                return true;
            return false;
        }

        public static bool operator !=(Vector v1, Vector v2)
        {
            return !(v1 == v2);
        }

        public override bool Equals(object o)
        {
            if ((o == null) || !(o is Vector))
                return false;

            var vector = (Vector) o;
            return Equals(this, vector);
        }

        public static bool Equals(Vector vector1, Vector vector2)
        {
            if (vector1.X.Equals(vector2.X))
            {
                return vector1.Y.Equals(vector2.Y);
            }
            return false;
        }

        public override int GetHashCode()
        {
            return (X.GetHashCode() ^ Y.GetHashCode());
        }

        public void Normalize()
        {
            this = (Vector) (this/Math.Max(Math.Abs(X), Math.Abs(Y)));
            this = (Vector) (this/Length);
        }

        public static Vector operator *(double scalar, Vector vector)
        {
            return new Vector(vector._x*scalar, vector._y*scalar);
        }

        public static Vector operator *(Vector vector, double scalar)
        {
            return new Vector(vector._x*scalar, vector._y*scalar);
        }

        public static Vector operator /(Vector vector, double scalar)
        {
            return (Vector) (vector*(1/scalar));
        }

        public static Vector operator +(Vector vector1, Vector vector2)
        {
            return new Vector(vector1._x + vector2._x, vector1._y + vector2._y);
        }

        public static Vector operator -(Vector vector1, Vector vector2)
        {
            return new Vector(vector1._x - vector2._x, vector1._y - vector2._y);
        }

        public static Vector operator -(Vector vector)
        {
            return new Vector(-vector._x, -vector._y);
        }

        public static double operator *(Vector vector1, Vector vector2)
        {
            return ((vector1._x*vector2._x) + (vector1._y*vector2._y));
        }

        public override string ToString()
        {
            return X + "," + Y;
        }

        public static implicit operator Point(Vector vector)
        {
            return new Point(vector.X, vector.Y);
        }

        public static implicit operator Vector(Vector2 vector)
        {
            return new Vector(vector.X, vector.Y);
        }

        public static implicit operator Vector2(Vector vector)
        {
            return new Vector2((float) vector.X, (float) vector.Y);
        }
    }
}